{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#### `Decorators` clearly explained! 🚀 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Hello, Python! You are awesome!\n"
     ]
    }
   ],
   "source": [
    "# Functions are first class objects!\n",
    "\n",
    "def greet(name):\n",
    "  return f'Hello, {name}!'\n",
    "\n",
    "def cheer(fun, name):\n",
    "  return fun(name) + ' You are awesome!'\n",
    "  \n",
    "print(cheer(greet, 'Python'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Before function call\n",
      "Hello, World!\n",
      "After function call\n"
     ]
    }
   ],
   "source": [
    "def decorate(fun):\n",
    "  def wrapper():\n",
    "    print(\"Before function call\")\n",
    "    fun()\n",
    "    print(\"After function call\")\n",
    "  return wrapper\n",
    "\n",
    "def greet():\n",
    "  print(\"Hello, World!\")\n",
    "\n",
    "greet = decorate(greet)\n",
    "greet()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Before function call\n",
      "Hello, Akshay!\n",
      "After function call\n"
     ]
    }
   ],
   "source": [
    "def decorate(fun):\n",
    "  def wrapper(arg):\n",
    "    print(\"Before function call\")\n",
    "    fun(arg)\n",
    "    print(\"After function call\")\n",
    "  return wrapper\n",
    "\n",
    "@decorate\n",
    "def greet(name):\n",
    "  print(f\"Hello, {name}!\")\n",
    "\n",
    "greet('Akshay')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:root:Executed fibonacci in 9.5367431640625e-07 seconds\n",
      "INFO:root:Executed fibonacci in 7.152557373046875e-07 seconds\n",
      "INFO:root:Executed fibonacci in 0.0016901493072509766 seconds\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "1\n"
     ]
    }
   ],
   "source": [
    "import time\n",
    "import logging\n",
    "\n",
    "logging.basicConfig(level=logging.INFO)\n",
    "\n",
    "def timer_decorator(func):\n",
    "    def wrapper(*args, **kwargs):\n",
    "        start_time = time.time()\n",
    "        result = func(*args, **kwargs)\n",
    "        end_time = time.time()\n",
    "        execution_time = end_time - start_time\n",
    "        logging.info(f\"Executed {func.__name__} in {execution_time} seconds\")\n",
    "        return result\n",
    "    return wrapper\n",
    "\n",
    "@timer_decorator\n",
    "def fibonacci(n):\n",
    "    if n <= 1:\n",
    "       return n\n",
    "    else:\n",
    "       return (fibonacci(n-1) + fibonacci(n-2))\n",
    "\n",
    "print(fibonacci(2))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "env_twitter",
   "language": "python",
   "name": "env_twitter"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
